﻿define(function (require, exports, moudles) {
    return function (jquery) {
        (function ($) {
            // Add posibility to scroll to selected option
            // usefull for select for example
            $.fn.scrollTo = function (elem) {
                $(this).scrollTop($(this).scrollTop() - $(this).offset().top + $(elem).offset().top);
                return this;
            };

            $.fn.dropdown = function (option) {
                var defaults = {
                    inDuration: 300,
                    outDuration: 225,
                    constrain_width: true, // Constrains width of dropdown to the activator
                    hover: false,
                    gutter: 0, // Spacing from edge
                    belowOrigin: false,
                    alignment: 'left'
                };

                this.each(function () {
                    var origin = $(this);
                    var options = $.extend({}, defaults, option);
                    var isFocused = false;

                    // Dropdown menu
                    var activates = $("#" + origin.attr('data-activates'));

                    function updateOptions() {
                        if (origin.data('induration') !== undefined)
                            options.inDuration = origin.data('inDuration');
                        if (origin.data('outduration') !== undefined)
                            options.outDuration = origin.data('outDuration');
                        if (origin.data('constrainwidth') !== undefined)
                            options.constrain_width = origin.data('constrainwidth');
                        if (origin.data('hover') !== undefined)
                            options.hover = origin.data('hover');
                        if (origin.data('gutter') !== undefined)
                            options.gutter = origin.data('gutter');
                        if (origin.data('beloworigin') !== undefined)
                            options.belowOrigin = origin.data('beloworigin');
                        if (origin.data('alignment') !== undefined)
                            options.alignment = origin.data('alignment');
                    }

                    updateOptions();

                    // Attach dropdown to its activator
                    origin.after(activates);

                    /*
                      Helper function to position and resize dropdown.
                      Used in hover and click handler.
                    */
                    function placeDropdown(eventType) {
                        // Check for simultaneous focus and click events.
                        if (eventType === 'focus') {
                            isFocused = true;
                        }

                        // Check html data attributes
                        updateOptions();

                        // Set Dropdown state
                        activates.addClass('active');
                        origin.addClass('active');

                        // Constrain width
                        if (options.constrain_width === true) {
                            activates.css('width', origin.outerWidth());

                        } else {
                            activates.css('white-space', 'nowrap');
                        }

                        // Offscreen detection
                        var windowHeight = window.innerHeight;
                        var originHeight = origin.innerHeight();
                        var offsetLeft = origin.offset().left;
                        var offsetTop = origin.offset().top - $(window).scrollTop();
                        var currAlignment = options.alignment;
                        var activatesLeft, gutterSpacing;

                        // Below Origin
                        var verticalOffset = 0;
                        if (options.belowOrigin === true) {
                            verticalOffset = originHeight;
                        }

                        if (offsetLeft + activates.innerWidth() > $(window).width()) {
                            // Dropdown goes past screen on right, force right alignment
                            currAlignment = 'right';

                        } else if (offsetLeft - activates.innerWidth() + origin.innerWidth() < 0) {
                            // Dropdown goes past screen on left, force left alignment
                            currAlignment = 'left';
                        }
                        // Vertical bottom offscreen detection
                        if (offsetTop + activates.innerHeight() > windowHeight) {
                            // If going upwards still goes offscreen, just crop height of dropdown.
                            if (offsetTop + originHeight - activates.innerHeight() < 0) {
                                var adjustedHeight = windowHeight - offsetTop - verticalOffset;
                                activates.css('max-height', adjustedHeight);
                            } else {
                                // Flow upwards.
                                if (!verticalOffset) {
                                    verticalOffset += originHeight;
                                }
                                verticalOffset -= activates.innerHeight();
                            }
                        }

                        // Handle edge alignment
                        if (currAlignment === 'left') {
                            gutterSpacing = options.gutter;
                            leftPosition = origin.position().left + gutterSpacing;
                        }
                        else if (currAlignment === 'right') {
                            var offsetRight = origin.position().left + origin.outerWidth() - activates.outerWidth();
                            gutterSpacing = -options.gutter;
                            leftPosition = offsetRight + gutterSpacing;
                        }

                        // Position dropdown
                        activates.css({
                            position: 'absolute',
                            top: origin.position().top + verticalOffset,
                            left: leftPosition
                        });


                        // Show dropdown
                        activates.stop(true, true).css('opacity', 0)
                          .slideDown({
                              queue: false,
                              duration: options.inDuration,
                              easing: 'easeOutCubic',
                              complete: function () {
                                  $(this).css('height', '');
                              }
                          })
                          .animate({ opacity: 1 }, { queue: false, duration: options.inDuration, easing: 'easeOutSine' });
                    }

                    function hideDropdown() {
                        // Check for simultaneous focus and click events.
                        isFocused = false;
                        activates.fadeOut(options.outDuration);
                        activates.removeClass('active');
                        origin.removeClass('active');
                        setTimeout(function () { activates.css('max-height', ''); }, options.outDuration);
                    }

                    // Hover
                    if (options.hover) {
                        var open = false;
                        origin.unbind('click.' + origin.attr('id'));
                        // Hover handler to show dropdown
                        origin.on('mouseenter', function (e) { // Mouse over
                            if (open === false) {
                                placeDropdown();
                                open = true;
                            }
                        });
                        origin.on('mouseleave', function (e) {
                            // If hover on origin then to something other than dropdown content, then close
                            var toEl = e.toElement || e.relatedTarget; // added browser compatibility for target element
                            if (!$(toEl).closest('.dropdown-content').is(activates)) {
                                activates.stop(true, true);
                                hideDropdown();
                                open = false;
                            }
                        });

                        activates.on('mouseleave', function (e) { // Mouse out
                            var toEl = e.toElement || e.relatedTarget;
                            if (!$(toEl).closest('.dropdown-button').is(origin)) {
                                activates.stop(true, true);
                                hideDropdown();
                                open = false;
                            }
                        });

                        // Click
                    } else {
                        // Click handler to show dropdown
                        origin.unbind('click.' + origin.attr('id'));
                        origin.bind('click.' + origin.attr('id'), function (e) {
                            if (!isFocused) {
                                if (origin[0] == e.currentTarget &&
                                     !origin.hasClass('active') &&
                                     ($(e.target).closest('.dropdown-content').length === 0)) {
                                    e.preventDefault(); // Prevents button click from moving window
                                    placeDropdown('click');
                                }
                                    // If origin is clicked and menu is open, close menu
                                else if (origin.hasClass('active')) {
                                    hideDropdown();
                                    $(document).unbind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'));
                                }
                                // If menu open, add click close handler to document
                                if (activates.hasClass('active')) {
                                    $(document).bind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'), function (e) {
                                        if (!activates.is(e.target) && !origin.is(e.target) && (!origin.find(e.target).length)) {
                                            hideDropdown();
                                            $(document).unbind('click.' + activates.attr('id') + ' touchstart.' + activates.attr('id'));
                                        }
                                    });
                                }
                            }
                        });

                    } // End else

                    // Listen to open and close event - useful for select component
                    origin.on('open', function (e, eventType) {
                        placeDropdown(eventType);
                    });
                    origin.on('close', hideDropdown);


                });
            }; // End dropdown plugin

            $(function () {
                $('.dropdown-button').dropdown();
            });
        })(jquery);
    }
})